﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Internal;
using Autodesk.AutoCAD.Runtime;

namespace AutoCADDotNetLibrary
{
    public static class Command
    {
        /// <summary>
        /// 移除命令
        /// </summary>
        /// <param name="ass">程序集</param>
        /// <param name="exceptTypes">不移除的类型</param>
        public static void Remove(Assembly ass, params Type[] exceptTypes)
        {
            var methods = ass.GetTypes().Except(exceptTypes).SelectMany(x => x.GetMethods()
                        .Select(y => new { Method = y, Atts = y.GetCustomAttributes(false).OfType<CommandMethodAttribute>().ToArray() }))
                        .Where(x => x.Atts.Length == 1)
                        .Select(x => new { Method = x.Method, Att = x.Atts.First() }).ToList();

            foreach (var item in methods)
            {
                //if (Utils.IsCommandDefined(item.Att.GlobalName))
                {
                    Utils.RemoveCommand(ass.FullName, item.Att.GlobalName);
                }
            }
        }


        private static List<ClassData> _objs = new List<ClassData>();
        /// <summary>
        /// 添加命令
        /// </summary>
        /// <param name="ass">程序集</param>
        /// <param name="exceptTypes">不移除的类型</param>
        public static void Add(Assembly ass, params Type[] exceptTypes)
        {
            var methods = ass.GetTypes().Except(exceptTypes).SelectMany(x => x.GetMethods()
                        .Select(y => new { Method = y, Atts = y.GetCustomAttributes(false).OfType<CommandMethodAttribute>().ToArray() }))
                        .Where(x => x.Atts.Length == 1)
                        .Select(x => new { Method = x.Method, Att = x.Atts.First() }).ToList();

            foreach (var item in methods)
            {
                //if (!Utils.IsCommandDefined(item.Att.GlobalName))
                {
                    Utils.AddCommand(item.Att.GroupName ?? ass.FullName, item.Att.GlobalName, item.Att.LocalizedNameId ?? item.Att.GlobalName, item.Att.Flags, () =>
                    {
                        if (item.Method.IsStatic)
                        {
                            item.Method.Invoke(null, null);
                        }
                        else
                        {
                            ClassData f = _objs.FirstOrDefault(x => (x.Database == Application.DocumentManager.MdiActiveDocument.Database && x.Type == item.Method.ReflectedType));
                            if (f == null)//重复利用类实例
                            {
                                f = new ClassData(Application.DocumentManager.MdiActiveDocument.Database, item.Method.ReflectedType,
                                    item.Method.ReflectedType.GetConstructor(new Type[] { }).Invoke(null));//空参数的构造函数
                                _objs.Add(f);
                            }
                            item.Method.Invoke(f.Object, null);
                        }
                    });
                }
            }
        }

        private class ClassData
        {
            public ClassData(Database database, Type type, object obj)
            {
                Database = database;
                Type = type;
                Object = obj;
            }

            public Database Database { get; }

            public Type Type { get; }

            public object Object { get; }
        }

    }
}
